package com.guodi.model.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.guodi.common.constant.StatusCode;
import com.guodi.common.utils.AjaxResult;
import com.guodi.common.utils.PageData;
import com.guodi.common.utils.UuidUtil;
import com.guodi.core.boot.ctrl.BaseController;
import com.guodi.model.constant.CommonConst;
import com.guodi.model.constant.ModelConst;
import com.guodi.model.entity.*;
import com.guodi.model.service.IMdlModelDirService;
import com.guodi.model.service.IMdlModelResultService;
import com.guodi.model.service.IMdlModelService;
import com.guodi.model.service.IMdlModelTypeService;
import com.guodi.model.service.impl.MdlModelResultServiceImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import javax.annotation.Resource;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @描述：模型结果表控制类
 * @作者: 代鹏刚
 * @日期: 2020-06-17
 */
@RestController
@RequestMapping("/MdlModelResult")
@Api(value = "API - MdlModelResultController", description = "模型结果表")
public class MdlModelResultController extends BaseController {

    @Resource
    public IMdlModelResultService mdlModelResultService;

    @Resource
    public IMdlModelTypeService mdlModelTypeService;

    @Resource
    public IMdlModelDirService mdlModelDirService;

    @Resource
    public IMdlModelService iMdlModelService;
    /**
    * @描述: 根据实体属性分页查询
    * @入参:
    * @出参:
    * @作者: 代鹏刚
    * @日期: 2020-06-17
    **/
    @PostMapping("/listByEntity")
    @ApiOperation(value = " 根据实体属性分页查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "current", value = "当前页码", required = true, dataType = "long", paramType = "query", example = "1"),
            @ApiImplicitParam(name = "size", value = "每页显示数量", required = true, dataType = "long", paramType = "query", example = "10"),
            @ApiImplicitParam(name = "keyWord", value = "关键字搜索", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "year", value = "年份搜索", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "sortType", value = "排序类型(1:更新时间 2:年份)", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "sortMethod", value = "排序方式(1:向下 2:向上)", required = true, dataType = "string", paramType = "query")
    })
    public AjaxResult listByEntity(@ApiIgnore Page page, @ApiIgnore MdlModelResult mdlModelResult, @ApiIgnore CommonConst commonConst){
        IPage<MdlModelResult> iPage = mdlModelResultService.listByEntity(page, mdlModelResult, commonConst);
        // 处理更新时间，如果更新时间为空，那就取创建时间
        iPage.getRecords().stream().forEach(result -> {
            if (Objects.isNull(result.getModifyTime())){
                result.setModifyTime(result.getCreateTime());
            }
        });
        return new AjaxResult(iPage);
    }

    /**
     * @描述:查询模型结果
     * @入参:
     * @出参:
     * @作者: 郑文彬
     * @日期: 2020/5/15 14:25
     **/
    @PostMapping("/queryModelResult")
    @ApiOperation(value = "查询模型结果")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "模型名称", required = false, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "year", value = "年份", required = false, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "startYear", value = "开始年份", required = false, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "endYear", value = "结束年份", required = false, dataType = "string", paramType = "query")
    })
    public AjaxResult queryModelResult(){
        PageData pd = new PageData(this.getRequest());
        List<MdlModelResult> results = mdlModelResultService.listByEntity(pd);
        return new AjaxResult(results);
    }

    /**
     * @描述: 根据主键查询
     * @入参:
     * @出参:
     * @作者: 代鹏刚
     * @日期: 2020-06-17
     **/
    @PostMapping("/findById")
    @ApiOperation(value = "根据主键查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "ID", required = true,
                    dataType = "string", paramType = "query")
    })
    public AjaxResult findById(String id) {
        if(StringUtils.isBlank(id)){
            return new AjaxResult(StatusCode.ERROR_CODE_40005,"id不能为空");
        }
        MdlModelResult mdlModelResult = mdlModelResultService.getById(id);
        return new AjaxResult(mdlModelResult);
    }

    /**
     * @描述: 新增
     * @入参:
     * @出参:
     * @作者: 代鹏刚
     * @日期: 2020-06-17
     **/
    @PostMapping("/save")
    @ApiOperation(value = "新增")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "模型结果名称", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "year", value = "年份", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "result", value = "模型结果",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "resultLayer", value = "结果图层",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "modelIds", value = "模型ID（多个逗号隔开）",  dataType = "string", paramType = "query")
    })
    public AjaxResult save(@ApiIgnore MdlModelResult mdlModelResult){
        prepareData(mdlModelResult, true);
        mdlModelResult.setId(UuidUtil.get32UUID());
        mdlModelResultService.save(mdlModelResult);
        return new AjaxResult();
    }

    /**
     * @描述: 修改
     * @入参:
     * @出参:
     * @作者: 代鹏刚
     * @日期: 2020-06-17
     **/
    @PostMapping("/update")
    @ApiOperation(value = "修改")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "year", value = "年份",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "result", value = "模型结果",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "resultLayer", value = "结果图层",  dataType = "string", paramType = "query")
    })
    public AjaxResult update(@ApiIgnore MdlModelResult mdlModelResult) {
        prepareData(mdlModelResult, false);
        mdlModelResultService.updateById(mdlModelResult);
        return new AjaxResult();
    }

    /**
     * @描述: 根据主键删除
     * @入参: id
     * @出参:
     * @作者: 代鹏刚
     * @日期: 2020-06-17
     **/
    @PostMapping("/delete")
    @ApiOperation(value = "根据主键删除")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ids", value = "多个使用逗号隔开", required = true, dataType = "string", paramType = "query")
    })
    public AjaxResult delete(String ids){
        String[] id = ids.split(",");
        mdlModelResultService.removeByIds(Arrays.asList(id));
        return new AjaxResult();
    }

    /**
    * @描述: 根据模型ID查询模型结果
    * @入参:
    * @出参:
    * @作者: 代鹏刚
    * @日期: 2020/6/27 14:52
    **/
    @PostMapping("/findByModelId")
    @ApiOperation(value = "根据模型ID查询模型结果")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "modelId", value = "模型ID", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "year", value = "年份", required = true, dataType = "string", paramType = "query")
    })
    public AjaxResult findByModelId(String modelId, String year){
        List<MdlModelResult> mdlModelResults = mdlModelResultService.findByModelId(modelId, year);
        MdlModel mdlModel =  iMdlModelService.getById(modelId);

        if(null != mdlModelResults && mdlModelResults.size() > 0){
            //通过modeId查询描述并添加进MdlModelResult
            if(mdlModel != null){
                MdlModelResult mdlModelResult = mdlModelResults.get(0);
                mdlModelResult.setExplain(mdlModel.getDescription());
                mdlModelResults.set(0,mdlModelResult);
            }
            return new AjaxResult(mdlModelResults.get(0));
        }
        return new AjaxResult();
    }

    /**
    * @描述: 根据模型获取因子关联模型结果
    * @入参:
    * @出参:
    * @作者: 代鹏刚
    * @日期: 2020/7/15 14:18
    **/
    @PostMapping("/statisticalByFactorId")
    @ApiOperation(value = "根据模型获取因子关联模型结果")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "modelId", value = "模型ID", required = true, dataType = "string", paramType = "query")
    })
    public AjaxResult statisticalByFactorId(String modelId){
        Map<String, Map<String, Object>> map = mdlModelResultService.statisticalByFactorId(modelId);
        return new AjaxResult(map);
    }

    @PostMapping("/getModelResultByCode")
    @ApiOperation(value = "规划分析-评价成果-整体介绍（返回模型体系下的模型结果列表，和优势劣势资源排序）")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "code", value = "模型体系编码", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "year", value = "模型结果年份", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "areaCode", value = "区域编码", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "keyWord", value = "关键字搜索字段", dataType = "string", paramType = "query")
    })
    public AjaxResult getModelResultByCode(String code, String areaCode, String year, String keyWord){
        if(StringUtils.isBlank(code)){
            return new AjaxResult(StatusCode.ERROR_CODE_40005,"模型类型编码不能为空");
        }
        LambdaQueryWrapper<MdlModelType> lambda = new QueryWrapper().lambda();
        lambda.eq(MdlModelType::getCode,code);
        MdlModelType one = mdlModelTypeService.getOne(lambda);
        List<ApiMdlModelDir> mdlModelDirs = mdlModelDirService.listTreeByEntity(one.getId(), null);
        //短板资源占比排名（评价结果为低的面积占比排名）
        List<HashMap> letdownData = new ArrayList<>();
        // 优势资源占比排名（评价结果为高的面积占比排名）
        List<HashMap> advantageData = new ArrayList<>();
        //饼图列表
        List<Map> list = new ArrayList<>();
        Map<String,List<JSONObject>> map = new TreeMap<>();
        List<JSONObject> jsonObjects = parseData(mdlModelDirs, year, areaCode, keyWord);
        for (int i = 0; i < jsonObjects.size() ; i++) {
            JSONObject jsonObject = jsonObjects.get(i);
            JSONArray evaluation = jsonObject.getJSONArray("Evaluation");
            if(evaluation!=null && evaluation.size()>0){
                //饼图分类
                if(map.get(jsonObject.getString("typeName"))==null){
                    List<JSONObject> listData = new ArrayList<>();
                    listData.add(jsonObject);
                    map.put(jsonObject.getString("typeName"),listData);
                }else {
                    List listData = map.get(jsonObject.getString("typeName"));
                    listData.add(jsonObject);
                }
                HashMap<String, Object> map1 = new HashMap<>();
                HashMap<String, Object> map2 = new HashMap<>();
                map1.put("name",jsonObjects.get(i).getString("modelResultName"));
                map2.put("name",jsonObjects.get(i).getString("modelResultName"));
                // 第一个为评价低的占比
                map1.put("Area",evaluation.getJSONObject(0).getString("Area"));
                map1.put("Percent",evaluation.getJSONObject(0).getString("Percent"));
                letdownData.add(map1);
                // 最后一个为评价高的占比
                map2.put("Area",evaluation.getJSONObject(evaluation.size()-1).getString("Area"));
                map2.put("Percent",evaluation.getJSONObject(evaluation.size()-1).getString("Percent"));
                advantageData.add(map2);
            }
        }

        //饼图组装前端需要的格式
        Set<String> keys = map.keySet();
        for (String key: keys) {
           Map<String, Object> data = new HashMap<>();
            data.put("name",key);
            data.put("listdata",map.get(key));
            list.add(data);
        }

        Map<String, Object> result = new HashMap<>();
        result.put("list",list);
        //排序
        sort(letdownData);
        sort(advantageData);
        result.put("letdownData",letdownData);
        result.put("advantageData",advantageData);

        return new AjaxResult(result);
    }

    public void sort( List<HashMap> list){
        Collections.sort(list, new Comparator<Map>() {
            @Override
            public int compare(Map o1, Map o2) {
                try {
                    double val1 = Double.valueOf((o1.get("Percent")+"").replaceAll("%",""));
                    double val2 =  Double.valueOf((o2.get("Percent")+"").replaceAll("%",""));
                    if (val1 > val2) {
                        return -1;
                    } else if (val1 < val2) {
                        return 1;
                    } else {
                        return 0;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return 0;
            }
        });
    }

    private List<JSONObject> parseData(List<ApiMdlModelDir> dirList, String year, String areaCode, String keyWord){
        //定义返回结果集
        List<JSONObject> resultList = new ArrayList<>();
        Map<String, ApiMdlModelDir> map = dirList.stream().collect(Collectors.toMap(ApiMdlModelDir::getId, Function.identity()));
        for (ApiMdlModelDir mapProjectDir:dirList) {
                try {
                    String modelId = mapProjectDir.getModelId();
                    if(StringUtils.isNotBlank(modelId)) {
                        //查询模型结果
                        LambdaQueryWrapper<MdlModelResult> lambda1 = new QueryWrapper().lambda();
                        lambda1.eq(MdlModelResult::getYear, year);
                        lambda1.like(MdlModelResult::getModelIds, modelId);
                        List<MdlModelResult> list1 = mdlModelResultService.list(lambda1);
                        if (list1 != null && list1.size() > 0) {
                            MdlModelResult mdlModelResult = list1.get(0);
                            String result = mdlModelResult.getResult();
                            //遍历查询模型结果 找到行政区划对应的数据
                            if (StringUtils.isNotBlank(result) && (StringUtils.isBlank(keyWord) || mdlModelResult.getName().contains(keyWord))) {
                                JSONObject jsonObject = JSONObject.fromObject(result);
                                if (areaCode.equals(jsonObject.getString("AreaCode"))) {
                                    //省级
                                    JSONArray jsonArray = jsonObject.getJSONObject(ModelConst.MODEL_STATISTICAL_STATISTICINFORMATION).getJSONArray("Evaluation");
                                    JSONObject parseResult = new JSONObject();
                                    parseResult.put("typeName", map.get(mapProjectDir.getParentId()).getName());
                                    parseResult.put("modelResultName", mdlModelResult.getName());
                                    parseResult.put("Name", jsonObject.getString("Name"));
                                    parseResult.put("AreaCode", jsonObject.getString("AreaCode"));
                                    parseResult.put("Evaluation", jsonArray);
                                    resultList.add(parseResult);
                                } else {
                                    // 遍历市级数据
                                    JSONArray lstCityModel = jsonObject.getJSONArray("LstCityModel");
                                    for (int i = 0; i < lstCityModel.size(); i++) {
                                        JSONObject cityData = lstCityModel.getJSONObject(i);
                                        if (areaCode.equals(cityData.getString("AreaCode"))) {
                                            JSONArray jsonArray = cityData.getJSONObject(ModelConst.MODEL_STATISTICAL_STATISTICINFORMATION).getJSONArray("Evaluation");
                                            JSONObject parseResult = new JSONObject();
                                            parseResult.put("typeName", map.get(mapProjectDir.getParentId()).getName());
                                            parseResult.put("modelResultName", mdlModelResult.getName());
                                            parseResult.put("Name", cityData.getString("Name"));
                                            parseResult.put("AreaCode", cityData.getString("AreaCode"));
                                            parseResult.put("Evaluation", jsonArray);
                                            resultList.add(parseResult);
                                        }
                                        // 遍历区县数据
                                        JSONArray lstCountyModel = cityData.getJSONArray(ModelConst.MODEL_STATISTICAL_LSTCOUNTYMODELEX);
                                        if (lstCountyModel != null && lstCountyModel.size() > 0) {
                                            for (int j = 0; j < lstCountyModel.size(); j++) {
                                                JSONObject countyData = lstCountyModel.getJSONObject(j);
                                                if (areaCode.equals(countyData.getString("AreaCode"))) {
                                                    JSONArray jsonArray = countyData.getJSONObject(ModelConst.MODEL_STATISTICAL_STATISTICINFORMATION).getJSONArray("Evaluation");
                                                    JSONObject parseResult = new JSONObject();
                                                    parseResult.put("typeName", map.get(mapProjectDir.getParentId()).getName());
                                                    parseResult.put("modelResultName", mdlModelResult.getName());
                                                    parseResult.put("Name", countyData.getString("Name"));
                                                    parseResult.put("AreaCode", countyData.getString("AreaCode"));
                                                    parseResult.put("Evaluation", jsonArray);
                                                    resultList.add(parseResult);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }catch (Exception e){
                   System.out.println(e.getMessage());
                }
        }
        return resultList;
    }

    /**
     * @描述: 根据模型主键统计历年数据
     * @入参:
     * @出参:
     * @作者: 汤厚韬
     * @日期: 2021/1/19 14:58
     **/
    @PostMapping("/getHistoryYearData")
    @ApiOperation(value = "根据模型主键统计历年数据")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "modelId", value = "模型主键", required = true, dataType = "string", paramType = "query")
    })
    public AjaxResult getHistoryYearData(String modelId){
        return new AjaxResult(mdlModelResultService.getHistoryYearData(modelId));
    }

    private void prepareData(MdlModelResult mdlModelResult, boolean isSave) {
        if(isSave){
            mdlModelResult.setCreator(this.getUser().getUserId().toString());
            mdlModelResult.setCreateTime(new Date());
            //防止误修改
            mdlModelResult.setModifier(null);
            mdlModelResult.setModifyTime(null);
        }else{
            mdlModelResult.setModifier(this.getUser().getUserId().toString());
            mdlModelResult.setModifyTime(new Date());
            //防止误修改
            mdlModelResult.setCreator(null);
            mdlModelResult.setCreateTime(null);
        }
    }
    /**
     * @作者: 林楷 2021/10/29
     * @描述: 查询资源环境承载力-综合监管模型结果
     * @参数:
     * @返回:
     */
    @PostMapping("/getZhjgModel")
    @ApiOperation(value = "查询综合监管模型结果")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "modelDirId", value = "模型目录ID", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "year", value = "年份", required = true, dataType = "string", paramType = "query")
    })
    public AjaxResult getZhjgModel(String modelDirId, String year){
        if(StringUtils.isBlank(modelDirId) || StringUtils.isBlank(year)) {
            return new AjaxResult(StatusCode.REQUEST_CODE_OPERATION_FAILURE, "模型目录,年份必填");
        }
        LambdaQueryWrapper<MdlModelDir> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MdlModelDir::getParentId, modelDirId);
        List<MdlModelDir> list = mdlModelDirService.list(queryWrapper);
        List<MdlModelResultServiceImpl.ApiResult> byList = mdlModelResultService.getZhjgByList(list, year);
        return new AjaxResult(byList);
    }
    /**
     * @作者: 林楷 2021/10/29
     * @描述: 资源环境承载力-决策支持模型结果
     * @参数:
     * @返回:
     */
    @PostMapping("/getJczcModel")
    @ApiOperation(value = "查询决策支持模型结果")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "code", value = "模型类型编码", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "year", value = "年份", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "division", value = "行政区划编码", required = true, dataType = "string", paramType = "query")
    })
    public AjaxResult getJczcModel(String code, String year, String division){
        if(StringUtils.isBlank(year) || StringUtils.isBlank(division)) {
            return new AjaxResult(StatusCode.REQUEST_CODE_OPERATION_FAILURE, "模型目录,年份,行政区必填");
        }
        MdlModelType modelType = mdlModelTypeService.getOne(new LambdaQueryWrapper<MdlModelType>().eq(MdlModelType::getCode, code));
        LambdaQueryWrapper<MdlModelDir> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MdlModelDir::getParentId, modelType.getId());
        List<MdlModelDir> list = mdlModelDirService.list(queryWrapper);
        List<Map<String, Object>> byList = mdlModelResultService.getJczcByList(list, year, division);
        return new AjaxResult(byList);
    }

//    /**
//     * @描述: 查询动态评估模型的超载情况数据 - 近三年情况 - 该年份, 该区划下一级区划的数据统计
//     * @入参:
//     * @出参:
//     * @作者: 余家鑫
//     * @日期: 2022/3/11 下午2:17
//     */
//    @PostMapping("/getDynamicEvaluationStatisticInfo")
//    @ApiOperation(value = "查询动态评估模型的超载情况数据")
//    public AjaxResult<DynamicEvaluationModelGetRespDTO> getDynamicEvaluationStatisticInfo( DynamicEvaluationModelGetReqVO reqVO){
//        DynamicEvaluationModelGetRespDTO resp = mdlModelResultService.getDynamicEvaluationStatisticInfo(reqVO);
//        return new AjaxResult(resp);
//    }

//    /**
//     * @描述: 查询综合监管汇总情况数据
//     * @入参:
//     * @出参:
//     * @作者: 余家鑫
//     * @日期: 2022/3/11 下午2:17
//     */
//    @PostMapping("/getComprehensiveSupervisionStatisticInfo")
//    @ApiOperation(value = "查询综合监管汇总情况数据")
//    public AjaxResult<List<MdlModelResultServiceImpl.ApiResult>> getComprehensiveSupervisionStatisticInfo( ComprehensiveSupervisionModelGetReqVO reqVO){
//        List<MdlModelResultServiceImpl.ApiResult> resps =  mdlModelResultService.getComprehensiveSupervisionStatisticInfo(reqVO);
//        return new AjaxResult(resps);
//    }


}
